using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using AutoMapper;
using DealerPlatform.Common.EventBusHelper;
using DealerPlatform.Core.Core;
using DealerPlatform.Core.Repository;
using DealerPlatform.Domain;
using DealerPlatform.Domain.GlobalDto;
using DealerPlatform.Service.ProductApp.Dto;
using DealerPlatform.Service.ShoppingCartApp.Dto;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;

namespace DealerPlatform.Service.ProductApp
{
    public partial class ProductService : IProductService
    {
        private readonly IRepository<Product> productRepo;
        private readonly IRepository<ProductPhoto> productPhotoRepo;
        private readonly IRepository<ProductSale> productSaleRepo;
        private readonly IRepository<ProductSaleAreaDiff> productSaleAreaDiffRepo;
        private readonly IMapper mapper;
        private readonly DealerPlatformContext context;

        public ProductService(
            IRepository<Product> productRepo,
            IRepository<ProductPhoto> productPhotoRepo,
            IRepository<ProductSale> productSaleRepo,
            IRepository<ProductSaleAreaDiff> productSaleAreaDiffRepo,
            IMapper mapper,
            DealerPlatformContext context,
            LocalEventBus<List<ShoppingCartDto>> localEventBus
        )
        {
            this.productRepo = productRepo;
            this.productPhotoRepo = productPhotoRepo;
            this.productSaleRepo = productSaleRepo;
            this.productSaleAreaDiffRepo = productSaleAreaDiffRepo;
            this.mapper = mapper;
            this.context = context;
            localEventBus.localEventHander += LocalEventHandler;
        }

        public async Task LocalEventHandler(List<ShoppingCartDto> dtos)
        {
            var products = await GetProdectByProductNo(dtos.Select(o=>o.ProductNo).ToArray());
            dtos.ForEach(d =>{
                var product = products.FirstOrDefault(p => p.ProductNo == d.ProductNo);
                d.ProductDto = product;
            });
        }

        public async Task<List<ProductDto>> GetProdectByProductNo(params string[] pnos){
            // var products = await productRepo.GetQueryable().Where(p=> pnos.Contains(p.ProductNo)).ToListAsync();
            // return mapper.Map<List<Product>, List<ProductDto>>(products);

            
            // 使用参数化查询构建 SQL 查询
            var query = $@"SELECT * FROM Products 
                            WHERE ProductNo IN ({string.Join(',', pnos.Select((_, i) => $"@p{i}"))})";

            // 执行查询并获取结果
            var products = context.Products
            .FromSqlRaw(query, pnos.Select((num, i) => new SqlParameter($"@p{i}", num)).ToArray())
            .ToList();
            return mapper.Map<List<Product>, List<ProductDto>>(products);
        }

        public async Task<IEnumerable<ProductDto>> GetProductDto(
            string BelongTypeNo, 
            string? typeNo, 
            string searchText, 
            Dictionary<string, string> dicProductProps, 
            PageWithSortDto pagedto)
        {
            dicProductProps.TryGetValue("ProductCd", out string Cd);
            dicProductProps.TryGetValue("ProductPp", out string Pp);
            dicProductProps.TryGetValue("ProductXh", out string Xh);
            dicProductProps.TryGetValue("ProductCz", out string Cz);
            dicProductProps.TryGetValue("ProductHb", out string Hb);
            dicProductProps.TryGetValue("ProductHd", out string Hd);
            dicProductProps.TryGetValue("ProductGy", out string Gy);
            dicProductProps.TryGetValue("ProductHs", out string Hs);
            dicProductProps.TryGetValue("ProductMc", out string Mc);
            dicProductProps.TryGetValue("ProductDj", out string Dj);
            dicProductProps.TryGetValue("ProductGg", out string Gg);
            dicProductProps.TryGetValue("ProductYs", out string Ys);
            dicProductProps.TryGetValue("ProductBzgg", out string Bzgg);

            int skip = (pagedto.PageIndex - 1) * pagedto.PageSize;
            List<Product> products = await productRepo.GetListAsync(m => m.BelongTypeNo==BelongTypeNo && 
            (string.IsNullOrWhiteSpace(typeNo) || m.TypeNo==typeNo)&& 
            (string.IsNullOrWhiteSpace(searchText) || m.ProductName.Contains(searchText))&&

            (string.IsNullOrWhiteSpace(Cd) || m.ProductCd==Cd)&&
            (string.IsNullOrWhiteSpace(Pp) || m.ProductPp==Pp)&&
            (string.IsNullOrWhiteSpace(Xh) || m.ProductXh==Xh)&&
            (string.IsNullOrWhiteSpace(Cz) || m.ProductCz==Cz)&&
            (string.IsNullOrWhiteSpace(Hb) || m.ProductHb==Hb)&&
            (string.IsNullOrWhiteSpace(Hd) || m.ProductHd==Hd)&&
            (string.IsNullOrWhiteSpace(Gy) || m.ProductGy==Gy)&&
            (string.IsNullOrWhiteSpace(Hs) || m.ProductHs==Hs)&&
            (string.IsNullOrWhiteSpace(Mc) || m.ProductMc==Mc)&&
            (string.IsNullOrWhiteSpace(Dj) || m.ProductDj==Dj)&&
            (string.IsNullOrWhiteSpace(Gg) || m.ProductGg==Gg)&&
            (string.IsNullOrWhiteSpace(Ys) || m.ProductYs==Ys)&&
            (string.IsNullOrWhiteSpace(Bzgg) || m.ProductBzgg==Bzgg)
            , pagedto);
            if(products==null||products.Count()==0)
            return new List<ProductDto>();
            var dto = mapper.Map<List<ProductDto>>(products);
            var photos = await GetProductPhotosByProductNo(dto.Select(p => p.ProductNo).ToArray());
            var sales = await GetProductSalesByProductNo(dto.Select(p => p.ProductNo).ToArray());
            dto.ForEach(product =>
            {
                var p = photos.Where(p => p.ProductNo == product.ProductNo).FirstOrDefault();
                if (p != null)
                    product = mapper.Map<ProductPhoto, ProductDto>(p, product);
                var s = sales.Where(p => p.ProductNo == product.ProductNo).FirstOrDefault();
                if (s != null)
                    product = mapper.Map<ProductSale, ProductDto>(s, product);
            });
            return dto;
        }

        public async Task<IEnumerable<ProductTypeDto>> GetProductType(string BelongTypeNo)
        {
            IEnumerable<ProductTypeDto> dtos = await context.Products
            .Where(p => p.BelongTypeNo == BelongTypeNo && !string.IsNullOrWhiteSpace(p.TypeName) && !string.IsNullOrWhiteSpace(p.TypeNo))
            .Select(p => new ProductTypeDto
            {
                TypeName = p.TypeName,
                TypeNo = p.TypeNo
            }).Distinct().ToListAsync();
            return dtos;
        }

        public async Task<Dictionary<string, IEnumerable<string>>> GetProductProperties(string bigType, string? typeNo)
        {
            Dictionary<string, IEnumerable<string>> props = new();
            var products = await productRepo.GetListAsync(p => p.BelongTypeNo == bigType && (p.TypeNo == typeNo || string.IsNullOrWhiteSpace(typeNo)));
            props.Add("ProductCd|产地", products.Select(p => p.ProductCd).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductPp|品牌", products.Select(p => p.ProductPp).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductXh|型号", products.Select(p => p.ProductXh).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductCz|材质", products.Select(p => p.ProductCz).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductHb|环保", products.Select(p => p.ProductHb).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductHd|厚度", products.Select(p => p.ProductHd).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductGy|工艺", products.Select(p => p.ProductGy).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductHs|产地", products.Select(p => p.ProductHs).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductMc|面材", products.Select(p => p.ProductMc).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductDj|等级", products.Select(p => p.ProductDj).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductGg|规格", products.Select(p => p.ProductGg).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductYs|颜色", products.Select(p => p.ProductYs).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            props.Add("ProductBzgg|包装规格", products.Select(p => p.ProductBzgg).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList());
            return props;
        }

        public async Task<List<ProductPropertyDto>> GetProductProperties2(string bigType, string? typeNo)
        {
            List<ProductPropertyDto> props = new();
            var products = await productRepo.GetListAsync(p => p.BelongTypeNo == bigType && (p.TypeNo == typeNo || string.IsNullOrWhiteSpace(typeNo)));
            props.Add(new ProductPropertyDto { FieldName = "ProductCd", FieldText = "产地", Items = products.Select(p => p.ProductCd).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductPp", FieldText = "品牌", Items = products.Select(p => p.ProductPp).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductXh", FieldText = "型号", Items = products.Select(p => p.ProductXh).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductCz", FieldText = "材质", Items = products.Select(p => p.ProductCz).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductHb", FieldText = "环保", Items = products.Select(p => p.ProductHb).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductHd", FieldText = "厚度", Items = products.Select(p => p.ProductHd).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductGy", FieldText = "工艺", Items = products.Select(p => p.ProductGy).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductHs", FieldText = "产地", Items = products.Select(p => p.ProductHs).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductMc", FieldText = "面材", Items = products.Select(p => p.ProductMc).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductDj", FieldText = "等级", Items = products.Select(p => p.ProductDj).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductGg", FieldText = "规格", Items = products.Select(p => p.ProductGg).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductYs", FieldText = "颜色", Items = products.Select(p => p.ProductYs).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            props.Add(new ProductPropertyDto { FieldName = "ProductBzgg", FieldText = "包装规格", Items = products.Select(p => p.ProductBzgg).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList() });
            
            return props;
        }
        
        public async Task<List<ProductBelongsDto>> GetProductBelongs()
        {
            var belongs = await productRepo.GetQueryable().Select(p => 
                new ProductBelongsDto{ SysNo=p.SysNo,BelongTypeNo=p.BelongTypeNo, BelongTypeName=p.BelongTypeName} ).Distinct().ToListAsync();
            return belongs;
        }
    }
}